package com.turbo.cloud.ods.web.logic;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.turbo.cloud.core.base.PageDynamic;
import com.turbo.cloud.core.base.PageQuery;
import com.turbo.cloud.core.exception.BusinessException;
import com.turbo.cloud.core.utils.PageUtil;
import com.turbo.cloud.ods.utils.SqlUtil;
import com.turbo.cloud.ods.utils.data.DataUtil;
import com.turbo.cloud.ods.web.entity.OdsReportSetting;
import com.turbo.cloud.ods.web.model.DynamicQueryQo;
import com.turbo.cloud.ods.web.model.DynamicQueryVo;
import com.turbo.cloud.ods.web.service.DynamicQueryService;
import com.turbo.cloud.ods.web.service.OdsReportSettingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * <p>
 * 动态SQL表 逻辑处理类
 * </p>
 *
 * @author zhangluning
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class DynamicQueryLogic {

    /**
     * Map key reportCode 报表编码
     */
    final static String MAP_KEY_REPORT_CODE = "reportCode";
    /**
     * Map key SqlStr SQL串
     */
    final static String MAP_KEY_SQL_STR = "sqlStr";


    final DynamicQueryService dynamicQueryService;
    final OdsReportSettingService odsReportSettingService;

    /**
     * 动态SQL分页列表
     *
     * @param pageQuery 分页查询参数
     * @return Page
     */
    public PageDynamic<Map<String, Object>> dynamicQueryPage(PageQuery<HashMap<String, String>> pageQuery) {
        HashMap<String, String> paramMap = pageQuery.getParam();

        if (Objects.isNull(paramMap)) {
            throw new BusinessException("查询条件不能为空");
        }
        if (StrUtil.isBlank(paramMap.get(MAP_KEY_REPORT_CODE))) {
            throw new BusinessException("报表编码不能为空");
        }
        LambdaQueryWrapper<OdsReportSetting> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(OdsReportSetting::getReportCode, paramMap.get(MAP_KEY_REPORT_CODE));
        OdsReportSetting odsReportSetting = odsReportSettingService.getOne(lambdaQueryWrapper);

        if (Objects.isNull(odsReportSetting)) {
            throw new BusinessException("报表SQL未配置");
        }

        String sqlStr = odsReportSetting.getSqlStr();
        String formatRuleJson = odsReportSetting.getSqlAnalysisJson();

        verifySelectSql(sqlStr);

        paramMap.put(MAP_KEY_SQL_STR, SqlUtil.joinSqlWhere(sqlStr, paramMap));
        pageQuery.setParam(paramMap);

        Page<Map<String, Object>> page = dynamicQueryService.dynamicQueryPage(pageQuery);
        DataUtil.formatMapPageData(page, formatRuleJson);

        List<PageDynamic.ColumnStyle> columns = JSON.parseArray(formatRuleJson, PageDynamic.ColumnStyle.class);

        return PageUtil.toPageDynamicView(page, columns);
    }

    /**
     * 执行动态SQL分页列表
     *
     * @param pageQuery 分页查询参数
     * @return Page
     */
    public Page<Map<String, Object>> executeDynamicQueryPage(PageQuery<HashMap<String, String>> pageQuery) {
        HashMap<String, String> paramMap = pageQuery.getParam();

        final String sqlStr = paramMap.get(MAP_KEY_SQL_STR);

        if (Objects.isNull(paramMap)) {
            throw new BusinessException("查询条件不能为空");
        }

        if (StrUtil.isBlank(sqlStr)) {
            throw new BusinessException("SQL字符串不能为空");
        }

        verifySelectSql(sqlStr);

        return dynamicQueryService.dynamicQueryPage(pageQuery);
    }

    /**
     * 解析SQL
     *
     * @param dynamicQueryQo 测试
     * @return Page
     */
    public List<DynamicQueryVo> analysisSql(DynamicQueryQo dynamicQueryQo) {
        String sqlStr = dynamicQueryQo.getSqlStr();

        verifySelectSql(sqlStr);

        List<String> columnList = SqlUtil.getSelectColumn(sqlStr);

        List<DynamicQueryVo> list = new ArrayList<>();

        if (!CollectionUtils.isEmpty(columnList)) {
            for (String column : columnList) {
                DynamicQueryVo dynamicQueryVo = new DynamicQueryVo();
                dynamicQueryVo.setColumnCode(column);
                list.add(dynamicQueryVo);
            }
        }

        return list;
    }

    /**
     * 验证SQL（Select语句、字段明确并字段有别名）
     *
     * @param sqlStr 字符串
     */
    private void verifySelectSql(String sqlStr) {
        if (!SqlUtil.verifySelectSql(sqlStr)) {
            throw new BusinessException("SQL语句只支持Select查询或SQL语法错误");
        }
        if (!SqlUtil.verifySelectSqlAndNoAsteriskColumn(sqlStr)) {
            throw new BusinessException("SQL语句Select查询必须明确查询字段不能使用(*)");
        }

        String msg = SqlUtil.verifySelectSqlAndHasAliasColumn(sqlStr);
        if (StrUtil.isNotBlank(msg)) {
            throw new BusinessException(msg);
        }
    }
}
